import os, sys, string
import subprocess

num_replica = 2
num_stripe = 4
#Cachesize calculator
cache_size = "`grep 'MemTotal' /proc/meminfo  | awk '{print $2 * 0.2 / 1024}' | cut -f1 -d.`"

class CreateVolfile:

    def __init__ (self, server_dict, server, transport,
                  transports, options, server_array):

        self.host_dict = server_dict
        self.host = server
        self.volume_name = options.volume_name
        self.transport = transport
        self.transports = transports
        self.gfs_port = options.port
        self.gfs_ib_port = options.port + 1
        self.auth_parameters = options.auth_param
        self.raid_type = options.raid_type
        self.ib_devport = options.ib_dev
        self.num_servers = len (self.host_dict.keys())
        self.conf_dir = options.conf_dir
        self.host_array = server_array
        self.unused = options.unused
        self.debug = options.debug

    def create_mount_volfile (self):

        raid_type = self.raid_type

        if self.conf_dir:
            mount_fd = file ("%s/%s-%s.vol" % (self.conf_dir,
                                               str(self.volume_name),
                                               str(self.transport)), "w")
        else:
            mount_fd = file ("%s-%s.vol" % (str(self.volume_name),
                                            str(self.transport)), "w")

        print "Generating client volfiles.. for transport '%s'" % (self.transport)


        cmdline = string.join (sys.argv, ' ')

        mount_fd.write ("## file auto generated by %s (mount.vol)\n" %
                        sys.argv[0])
        mount_fd.write ("# Cmd line:\n")
        mount_fd.write ("# $ %s\n\n" % cmdline)

        if raid_type is not None:
            # Used for later usage
            mount_fd.write ("# RAID %d\n" % raid_type)

        mount_fd.write ("# TRANSPORT-TYPE %s\n" % self.transport)
        subvolumes = []
        for host in self.host_dict.keys():
            i = 1
            for exports in self.host_dict[host]:
                mount_fd.write ("volume %s-%s\n" % (host,i))
                mount_fd.write ("    type protocol/client\n")
                mount_fd.write ("    option transport-type %s\n" %
                                self.transport)
                command = "dig %s | grep '^%s'" % (host, host)
                ps = subprocess.Popen(command,
                                      shell=True,
                                      stdout=subprocess.PIPE,
                                      stdin=subprocess.PIPE,
                                      stderr=subprocess.PIPE,
                                      close_fds=True)
                ipaddress = host
                if ps.wait() == 0:
                    output = ps.communicate()
                    ipaddress = output[0].split()[-1]

                mount_fd.write ("    option remote-host %s\n" % ipaddress)
                if self.transport == 'ib-verbs':
                    mount_fd.write ("    option transport.ib-verbs.port %d\n" %
                                    self.ib_devport)
                    mount_fd.write ("    option transport.remote-port %d\n" %
                                    self.gfs_ib_port)
                if self.transport == 'tcp':
                    mount_fd.write ("    option transport.socket.nodelay on\n")
                    mount_fd.write ("    option transport.remote-port %d\n" %
                                    self.gfs_port)

                mount_fd.write ("    option remote-subvolume brick%s\n" %
                                i)
                mount_fd.write ("end-volume\n\n")
                i += 1

        exportlist = {}
        for entry in self.host_array:
            node = entry.split(':')[0]
            if not exportlist.has_key(node):
                exportlist[node] = 1
            else:
                exportlist[node] += 1
            subvolumes.append(str(node) + '-' + str(exportlist[node]))

        # Stripe section.. if given
        if raid_type is 0:
            max_stripe_idx = len (subvolumes) / num_stripe
            stripe_idx = 0
            index = 0
            while index < max_stripe_idx:
                mount_fd.write ("volume stripe-%d\n" % index)
                mount_fd.write ("    type cluster/stripe\n")
                if self.unused:
                    mount_fd.write ("#    option block-size 128k\n")
                    mount_fd.write ("#    option use-xattr no\n")

                mount_fd.write ("    subvolumes %s %s %s %s\n" %
                                (subvolumes[stripe_idx],
                                 subvolumes[stripe_idx+1],
                                 subvolumes[stripe_idx+2],
                                 subvolumes[stripe_idx+3]))
                mount_fd.write ("end-volume\n\n")
                stripe_idx += 4
                index +=1

        # Replicate section
        if raid_type is 1:
            max_mirror_idx = len (subvolumes) / num_replica
            mirror_idx = 0
            index = 0
            while index < max_mirror_idx:
                mount_fd.write ("volume mirror-%d\n" % index)
                mount_fd.write ("    type cluster/replicate\n")
                mount_fd.write ("    subvolumes %s %s\n" %
                                (subvolumes[mirror_idx],
                                 subvolumes[mirror_idx+1]))
                mount_fd.write ("end-volume\n\n")
                mirror_idx += 2
                index += 1

        # Distribute section
        if raid_type is 0:
            subvolumes = []
            flag = 0
            while flag < index:
                subvolumes.append ("stripe-%d" % flag)
                flag += 1
        if raid_type is 1:
            subvolumes = []
            flag = 0
            while flag < index:
                subvolumes.append ("mirror-%d" % flag)
                flag += 1

        if len (subvolumes) > 1:
            mount_fd.write ("volume distribute\n")
            mount_fd.write ("    type cluster/distribute\n")
            if self.unused:
                mount_fd.write("# option unhashed-sticky-bit yes # Used for migrating data while adding new nodes\n")
                mount_fd.write("# option min-free-disk 5% # Minimum free disk available on the volume\n")


            mount_fd.write ("    subvolumes %s\n" %
                                 string.join (subvolumes,' '))
            mount_fd.write ("end-volume\n\n")
            subvolumes[0] = "distribute"

        mount_fd.write ("volume writebehind\n")
        mount_fd.write ("    type performance/write-behind\n")
        mount_fd.write ("    option cache-size 4MB\n")
        if self.unused:
            mount_fd.write ("#   option enable-trickling-writes yes # Flush final write calls when network is free\n")
            mount_fd.write ("#   option enable-O_SYNC yes # Enable O_SYNC for write-behind\n")
            mount_fd.write ("#   option disable-for-first-nbytes 1 # Disable first nbytes with very small initial writes\n")

        mount_fd.write ("    subvolumes %s\n" % subvolumes[0])
        mount_fd.write ("end-volume\n\n")

        mount_fd.write ("volume readahead\n")
        mount_fd.write ("    type performance/read-ahead\n")
        mount_fd.write ("    option page-count 4\n")

        if self.unused:
            mount_fd.write ("#   option force-atime-update yes # force updating atimes, default off\n")
        mount_fd.write ("    subvolumes writebehind\n")
        mount_fd.write ("end-volume\n\n")

        mount_fd.write ("volume iocache\n")
        mount_fd.write ("    type performance/io-cache\n")
        mount_fd.write ("    option cache-size %sMB\n" % cache_size)
        mount_fd.write ("    option cache-timeout 1\n")
        if self.unused:
            mount_fd.write ("#   option priority *.html:1,abc*:2 # Priority list for iocaching files\n")
        mount_fd.write ("    subvolumes readahead\n")
        mount_fd.write ("end-volume\n\n")

        mount_fd.write ("volume quickread\n")
        mount_fd.write ("    type performance/quick-read\n")
        mount_fd.write ("    option cache-timeout 1\n")
        mount_fd.write ("    option max-file-size 64kB\n")
        mount_fd.write ("    subvolumes iocache\n")
        mount_fd.write ("end-volume\n\n")

        mount_fd.write ("volume statprefetch\n")
        mount_fd.write ("    type performance/stat-prefetch\n")
        mount_fd.write ("    subvolumes quickread\n")
        mount_fd.write ("end-volume\n\n")

        return

    def create_export_volfile (self):

        cmdline = string.join (sys.argv, ' ')

        if self.conf_dir:
            exp_fd = file ("%s/%s-export.vol" %
                           (self.conf_dir,
                            str(self.host + '-' + self.volume_name)),"w")
        else:
            exp_fd = file ("%s-export.vol" %
                           (str(self.host + '-' + self.volume_name)),"w")

        print "Generating server volfiles.. for server '%s'" % (self.host)

        exp_fd.write ("## file auto generated by %s (export.vol)\n" %
                      sys.argv[0])
        exp_fd.write ("# Cmd line:\n")
        exp_fd.write ("# $ %s\n\n" % cmdline)
        total_bricks = []
        i=1
        for export in self.host_dict[self.host]:
            exp_fd.write ("volume posix%d\n" % i)
            exp_fd.write ("  type storage/posix\n")
            if self.unused:
                exp_fd.write("# option o-direct enable # (default: disable) boolean type only\n")
                exp_fd.write("# option export-statfs-size no # (default: yes) boolean type only\n")
                exp_fd.write("# option mandate-attribute off # (default: on) boolean type only\n")
                exp_fd.write("# option span-devices 8 # (default: 0) integer value\n")
                exp_fd.write("# option background-unlink yes # (default: no) boolean type\n")

            exp_fd.write ("  option directory %s\n" % export)
            exp_fd.write ("end-volume\n\n")

            exp_fd.write ("volume locks%d\n" % i)
            exp_fd.write ("    type features/locks\n")
            if self.unused:
                exp_fd.write ("#   option mandatory on # Default off, used in specific applications\n")

            exp_fd.write ("    subvolumes posix%d\n" % i)
            exp_fd.write ("end-volume\n\n")

            exp_fd.write ("volume brick%d\n" % i)
            exp_fd.write ("    type performance/io-threads\n")
            exp_fd.write ("    option thread-count 8\n")
            if self.unused:
                exp_fd.write ("#    option autoscaling yes # Heuristic for autoscaling threads on demand\n")
                exp_fd.write ("#    option min-threads 2 # min count for thread pool\n")
                exp_fd.write ("#    option max-threads 64 # max count for thread pool\n")

            exp_fd.write ("    subvolumes locks%d\n" % i)
            exp_fd.write ("end-volume\n\n")

            total_bricks.append("brick%s" % i)
            i += 1

        for transport in self.transports:
            exp_fd.write ("volume server-%s\n" % transport)
            exp_fd.write ("    type protocol/server\n")
            exp_fd.write ("    option transport-type %s\n" % transport)
            for brick in total_bricks:
                exp_fd.write ("    option auth.addr.%s.allow %s\n" %
                              (brick, self.auth_parameters))

            if transport == 'ib-verbs':
                exp_fd.write ("    option transport.ib-verbs.listen-port %d\n" % self.gfs_ib_port)
                exp_fd.write ("    option transport.ib-verbs.port %d\n" %
                              self.ib_devport)
            if transport == 'tcp':
                exp_fd.write ("    option transport.socket.listen-port %d\n" % self.gfs_port)
                exp_fd.write ("    option transport.socket.nodelay on\n")

            exp_fd.write ("    subvolumes %s\n" %
                          string.join(total_bricks, ' '))
            exp_fd.write ("end-volume\n\n")

        return
